package main

import (
	authhandlers "code.google.com/p/jesus-1496/auth/handlers"
	"code.google.com/p/jesus-1496/handlers"
	"code.google.com/p/jesus-1496/servererror"
	"code.google.com/p/jesus-1496/serverlog"
	"code.google.com/p/jesus-1496/settings"
	_ "code.google.com/p/jesus-1496/stores/pqstorer"
	"code.google.com/p/jesus-1496/utils/env"
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
	"path"
)

var logger = serverlog.NewServerLog("main")

type serverHandler func(http.ResponseWriter, *http.Request) *servererror.ServerError

func main() {
	router := mux.NewRouter()
	router.Handle("/", serverHandler(handlers.IndexHandler)).Methods("GET")
	router.Handle("/", serverHandler(authhandlers.LoginHandler)).Methods("POST")
	router.Handle("/logout", serverHandler(authhandlers.LogoutHandler))
	router.Handle("/humans", serverHandler(handlers.ClassDataGetHandler)).Methods("GET")
	//Static handlers. These can probably be improved, eg. Not displaying contents of folders.
	router.Handle("/media/{filepath:.*}", http.StripPrefix("/media", http.FileServer(http.Dir(path.Join(env.GetProjectDir(), "media")))))
	router.Handle("/static/{filepath:.*}", http.StripPrefix("/static", http.FileServer(http.Dir(path.Join(env.GetProjectDir(), "static")))))
	//Following is needed so that the login handler know what to do with a successful login. Probably a better way to do this.
	authhandlers.SetLoginSuccessHandler(handlers.HomeHandler)
	listenAddress := settings.Settings.Server.ListenIp + ":" + fmt.Sprintf("%d", settings.Settings.Server.ListenPort)
	logger.Printf("Listening on: %s.\n", listenAddress)
	http.ListenAndServe(listenAddress, router)
}

func (fn serverHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if e := fn(w, r); e != nil { //e is *servererror.ServerError, not error.
		logger.Printf("Error: %v\nStack trace: %s\nMessage: %s\n", e.Error, e.StackTrace, e.Message)
		t, _, err := env.NewHtmlTemplateFromFile("error.html")
		if err != nil {
			logger.Printf("Error creating error template: %v\n", err)
			http.Error(w, e.Message, e.Code)
			return
		}
		w.Header().Set("Content-Type", "text/html")
		err = t.Execute(w, e)
		if err != nil {
			logger.Printf("Error executing template: %v.", err)
		}
	}
	//TODO: More things to add:
	// - Add stack trace to html response if user is an admin
	// - Write a constructor to ServerError that stores the stack trace for easier debugging
	// - Recover from panics, log the critical error to console and tell user a 'serious error has occurred'.
}
